package com.example.demo.limiter;

import java.util.ArrayList;
import java.util.List;

public class SlidingWindowLimiter {

    /**
     * 每个窗口的最大请求数量
     */
    public static long threshold = 10;
    /**
     * 窗口大小，1000ms
     */
    public static long windowUnit = 1000;
    /**
     * 请求集合，用来存储窗口内的请求数量
     */
    public static List<Long> requestList = new ArrayList<>();

    /**
     * 限流方法，返回true表示通过
     */
    public boolean acquire() {
        long currentTime = System.currentTimeMillis();
        // 统计当前窗口内，有效的请求数量
        int sizeOfValid = this.sizeOfValid(currentTime);
        // 判断是否超过最大请求数量
        if (sizeOfValid < threshold) {
            // 把当前请求添加到请求集合里
            requestList.add(currentTime);
            return true;
        }
        return false;
    }

    /**
     * 统计当前窗口内，有效的请求数量
     */
    private int sizeOfValid(long currentTime) {
        int sizeOfValid = 0;
        for (Long requestTime : requestList) {
            // 判断是否在当前时间窗口内
            if (currentTime - requestTime <= windowUnit) {
                sizeOfValid++;
            }
        }
        return sizeOfValid;
    }

    /**
     * 清理过期的请求（单独启动一个线程处理）
     */
    private void clean() {
        // 判断是否超出当前时间窗口内
        requestList.removeIf(requestTime -> System.currentTimeMillis() - requestTime > windowUnit);
    }
}
